#include "app_buffer.h"
#include "log.h"
#include "string.h"
#include "stdlib.h"
#include "pthread.h"



/**
 * @brief 缓冲区的初始化
 * 1 初始化父缓冲结构体
 * 
 * 2 初始化两个子缓冲区结构体
 * 3 子缓冲区数据开辟空间
 * 
 */
app_buffer_t *app_buffer_init()
{
    // 1 初始化父缓冲结构体
    app_buffer_t *buffer =  malloc(sizeof(app_buffer_t));
    buffer->read_index = 0;
    buffer->write_index = 1;
    pthread_mutex_init(&buffer->read_lock,NULL);
    pthread_mutex_init(&buffer->swap_lock,NULL);
    //2 初始化两个子缓冲区结构体
    for (int i = 0; i < 2; i++)
    {
         sub_buffer_t *sub_buffer = malloc(sizeof(sub_buffer_t));
         //3 子缓冲区数据开辟空间
         sub_buffer->data_ptr = malloc(BUFFER_SIZE);
         sub_buffer->buff_total_len=BUFFER_SIZE;
         sub_buffer->buff_data_len=0;
         buffer->sub_buffers[i]=sub_buffer;
    }
    
    return buffer;

}

/**
 * 缓冲区的写操作
 * @return 写入成功返回0，失败返回-1
 * 0 取出写缓冲 
 * 1 检查剩余写缓存空间是否足够继续写入
 * 2 检查数据长度不能超过127
 * 3 先写入帧头 数据长度  占1个字节
 * 4 写入业务数据  占data_len个字节
 * 5 增加缓冲区数据长度 buff_data_len
 * 6 返回写入成功
 * 
 */
int app_buffer_write(app_buffer_t *buffer, char *write_data, int write_data_len)
{ 
    pthread_mutex_lock(&buffer->swap_lock);
    //0 取出写缓冲 
    sub_buffer_t *write_buffer = buffer->sub_buffers[buffer->write_index];
    // * 1 检查剩余写缓存空间是否足够继续写入
    int remain_write_len = write_buffer->buff_total_len - write_buffer->buff_data_len;
    if (write_data_len > remain_write_len)
    {   
        log_error("剩余写缓存空间不足");
        return -1;
    }
    // * 2 检查数据长度不能超过127
    if (write_data_len > 127)
    {
        log_error("数据长度不能超过127");
        return -1;
    }
    // * 3 先写入帧头 数据长度  占1个字节
    write_buffer->data_ptr[write_buffer->buff_data_len] = write_data_len;
    // * 4 写入业务数据  占data_len个字节
    memcpy(write_buffer->data_ptr+write_buffer->buff_data_len + 1 , write_data, write_data_len);

    // * 5 增加缓冲区数据长度 buff_data_len
    write_buffer->buff_data_len += write_data_len + 1;
    pthread_mutex_unlock(&buffer->swap_lock);
    // * 6 返回写入成功
    return 0;
}


void  buffer_swap(app_buffer_t *buffer)
{
    pthread_mutex_lock(&buffer->swap_lock);
    buffer->read_index= buffer->read_index==0?1:0;
    buffer->write_index= buffer->write_index==0?1:0;
    pthread_mutex_unlock(&buffer->swap_lock);
}

/**
 * 缓冲区的读操作
 * @return 读出成功返回 实际读出的长度，失败返回-1
 * 0  取出当前读缓冲区
 * 1  判断当前是否有数据可读，
 * 2  如果没有数据可读 进行缓冲区切换 
 * 3  如果还没有数据则 没有数据返回0
 * 4  如果有 先读取帧头 获得数据长度 
 * 5  参数缓冲区的长度要大于 可读数据长度
 * 6  把数据读取到参数的缓冲区中
 * 7  把后面的数据覆盖到已经读取的数据上面
 * 8  缩减读缓冲区的长度
 * 9  返回可读数据长度
 * 
 * 
 */
int app_buffer_read(app_buffer_t *buffer, char *read_data_buff, int read_buff_len)
{
    

   //A
    pthread_mutex_lock(&buffer->read_lock) ;
    // * 0  取出当前读缓冲区
    sub_buffer_t *read_buff = buffer->sub_buffers[buffer->read_index];
    // * 1  判断当前是否有数据可读 
    if(read_buff->buff_data_len == 0)
    { // * 2  如果没有数据可读 进行缓冲区切换 
         //B
        buffer_swap( buffer);
        //重新取出当前读缓冲区
        read_buff = buffer->sub_buffers[buffer->read_index];
        // * 3  如果还没有数据则 没有数据返回0
        if(read_buff->buff_data_len == 0)
        {
            return 0;
        }
    }
    //c
    // * 4  如果有 先读取帧头 获得数据长度 
    int read_data_len= read_buff->data_ptr[0];

    // * 5  参数缓冲区的长度要大于 可读数据长度
    if(read_data_len>read_buff_len)
    {
        log_error("可读数据长度超过参数冲去长度");
        return -1;
    }
    // * 6  把数据读取到参数的缓冲区中
    //D
    memcpy( read_data_buff ,read_buff->data_ptr+1,read_data_len);

    // * 7  把后面的数据覆盖到已经读取的数据上面
    memmove(read_buff->data_ptr,read_buff->data_ptr+read_data_len+1,read_buff->buff_data_len-read_data_len-1);

    // * 8  缩减读缓冲区的长度
    read_buff->buff_data_len = read_buff->buff_data_len-read_data_len-1;

      pthread_mutex_unlock(&buffer->read_lock) ;
    // * 9  返回可读数据长度
    return read_data_len;

 
}


/** 缓冲区销毁
 */
void app_buffer_destroy(app_buffer_t *buffer)
{


    //1  释放子缓冲区
    for (size_t i = 0; i < 2; i++)
    {
        free( buffer->sub_buffers[i]->data_ptr  );
        free( buffer->sub_buffers[i]);
    }
    pthread_mutex_destroy(&buffer->read_lock);
    pthread_mutex_destroy(&buffer->swap_lock);
    free(buffer);

}